<?php
class Product
{
    public $name;
    public $price;
    function __construct($name, $price)
    {
        $this->name = $name;
        $this->price = $price;
    }
}
class ProcessSale
{
    private $callback;
    function registerCallback($callback)
    {
        if (!is_callable($callback)) {
            //check callback function .that throw  the excptions;
            throw new Exception('callback not callable');
        }
        $this->callbacks[] = $callback;
    }
    function sale($product)
    {
        print "($product->name):processing \n";
        foreach ($this->callbacks as $callback) {
            call_user_func($callback, $product);
        }
    }
}
$logger = create_function('$product', 'print "logging
    (  {$product->name}.{$product->price})\n";');
$processSale = new ProcessSale();
$processSale->registerCallback($logger);
$processSale->sale(new Product("shoes", 6));
print "\n";
$processSale->sale(new Product("coffee", 6));
//通过 ProcessSable 的
// after php 5.4
$logger2 = function ($product) {
    print "logging({$product->name}.{$product->price})   by logger2";
};
$processSale2 = new ProcessSale();
print "\n";
$processSale2->registerCallback($logger2);
$processSale2->sale(new Product('show', 6));
print "<br>";
$processSale2->sale(new Product('coffese', 6));
class Mailler
{
    function doMail($product)
    {
        print " mailing({$product->name}) \n";
    }
    static function warnAmout()
    {
        return function ($project) {
            if ($project->price > 5) {
                print " height price reached:($project->price)<br>";
            } else {
                print "<br>too small for prices";
            }
        };
    }
}
$processSale->registerCallback(array(new Mailler(), "doMail"));

$processSale->sale(new Product("shoes", 6));
print "<br>";
$processSale->sale(new Product("coffess", 10));
//调用静态的匿名函数 来用于回调
$processSale->registerCallback(Mailler::warnAmout());

$processSale->sale(new Product("coffess", 10));
$processSale->sale(new Product("test", 4));
class Totalizer
{
    static function warnAmout($amt)
    {
        $count = 0;
        return function ($product) use ($amt, &$count) {
            $count += $product->price;
            print " count:$count \n";
            if ($count > $amt) {
                print "height price reached:{$count}\n";
            }
        };
    }
}
$processSale->registerCallback(Totalizer::warnAmout(9));
$processSale->sale(new Product("shoes",6));
$processSale->sale(new Product("coffess",7));

?>